package com.ziyucoding.springboot.labs.redislike.service.impl;

import com.ziyucoding.springboot.labs.redislike.common.Constant;
import com.ziyucoding.springboot.labs.redislike.dto.UserLikeCountDTO;
import com.ziyucoding.springboot.labs.redislike.dto.UserLikesDTO;
import com.ziyucoding.springboot.labs.redislike.utils.LocalDateTimeConvertUtil;
import com.ziyucoding.springboot.labs.redislike.utils.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;
import com.ziyucoding.springboot.labs.redislike.service.RedisLikeService;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Redis 点赞服务 实现类
 *
 * @author ziyucoding
 * @date 2023-02-07
 **/
@Service("RedisLikeService")
public class RedisLikeServiceImpl implements RedisLikeService {

    @Autowired
    private HashOperations<String, String, Object> redisHash;

    @Override
    public Integer getLikeStatus(String infoId, String likeUserId) {
        String key = RedisKeyUtil.MAP_KEY_USER_LIKED;
        String hashKey = RedisKeyUtil.getLikedKey(infoId, likeUserId);
        if (redisHash.hasKey(key, hashKey)) {
            HashMap<String, Object> map = (HashMap<String, Object>) redisHash.get(key, hashKey);
            return (Integer) map.get("status");
        }
        return Constant.LikedStatusEum.NOT_EXIST.getCode();
    }

    @Override
    public void saveLiked2Redis(String infoId, String likeUserId) {
        String hashKey = RedisKeyUtil.getLikedKey(infoId, likeUserId);
        HashMap<String, Object> map = new HashMap<>();
        map.put("status", Constant.LikedStatusEum.LIKE.getCode());
        map.put("updateTime", System.currentTimeMillis());
        String key = RedisKeyUtil.MAP_KEY_USER_LIKED;
        redisHash.put(key, hashKey, map);
    }

    @Override
    public void unlikeFromRedis(String infoId, String likeUserId) {
        String hashKey = RedisKeyUtil.getLikedKey(infoId, likeUserId);
        HashMap<String, Object> map = new HashMap<>();
        map.put("status", Constant.LikedStatusEum.UNLIKE.getCode());
        map.put("updateTime", System.currentTimeMillis());
        String key = RedisKeyUtil.MAP_KEY_USER_LIKED;
        redisHash.put(key, hashKey, map);
    }

    @Override
    public void deleteLikedFromRedis(String infoId, String likeUserId) {
        String hashKey = RedisKeyUtil.getLikedKey(infoId, likeUserId);
        String key = RedisKeyUtil.MAP_KEY_USER_LIKED;
        redisHash.delete(key, hashKey);
    }

    @Override
    public void inDecrementLikedCount(String infoId, Integer delta) {
        String key = RedisKeyUtil.MAP_KEY_USER_LIKED_COUNT;
        redisHash.increment(key, infoId, delta);
    }

    @Override
    public List<UserLikesDTO> getLikedDataFromRedis() {
        String key = RedisKeyUtil.MAP_KEY_USER_LIKED;
        // scan 读取数据，比key匹配优雅
        Cursor<Map.Entry<String, Object>> cursor = redisHash.scan(key, ScanOptions.NONE);

        List<UserLikesDTO> userLikesDTOList = new ArrayList<>();
        while (cursor.hasNext()) {
            Map.Entry<String, Object> entry = cursor.next();
            String entryKey = entry.getKey();
            // 分离出 infoId、likeUserId，解析 value
            String[] keys = entryKey.split("::");
            String infoId = keys[0];
            String likeUserId = keys[1];
            Map<String, Object> itemMap = (HashMap<String, Object>) entry.getValue();
            Integer status = (Integer) itemMap.get("status");
            Long updateTimeStamp = (Long) itemMap.get("updateTime");
            LocalDateTime updateTime = LocalDateTimeConvertUtil.getDateTimeOfTimestamp(updateTimeStamp);

            // 组装成 UserLike 对象
            UserLikesDTO userLikesDTO = new UserLikesDTO(infoId, likeUserId, status, updateTime);
            userLikesDTOList.add(userLikesDTO);

            // 存储 userLikesDTOList 后，从 redis 中清除缓存
            redisHash.delete(key, entryKey);
        }

        return userLikesDTOList;
    }

    @Override
    public List<UserLikeCountDTO> getLikedCountFromRedis() {
        String key = RedisKeyUtil.MAP_KEY_USER_LIKED_COUNT;
        // scan 读取数据，比key匹配优雅
        Cursor<Map.Entry<String, Object>> cursor = redisHash.scan(key, ScanOptions.NONE);
        List<UserLikeCountDTO> userLikeCountDTOList = new ArrayList<>();
        while (cursor.hasNext()) {
            Map.Entry<String, Object> entry = cursor.next();
            String infoId = entry.getKey();
            Integer likeCount = (Integer) entry.getValue();
            UserLikeCountDTO userLikeCountDTO = new UserLikeCountDTO(infoId, likeCount);
            userLikeCountDTOList.add(userLikeCountDTO);

            // 从 Redis 中删除该记录
            redisHash.delete(key, infoId);
        }
        return userLikeCountDTOList;
    }

}
